/// @tags: SegmentTree Diameter
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

namespace BlueQuantum {

typedef long long LL;

int const N = 4e5 + 5, M = 1e6 + 5, ST = 19;

int ecnt;
int heads[N];
int segcnt, n, m, maxdep, dcnt;
int st[N * 2][ST], dep[N], fw[N], lg[N * 2], rt[N], euler[N * 2], dfn[N];
vector<int> q[N];
LL ans, sum, dis[N];

struct Edge {
  int v, nxt, w;
} e[N * 2];

inline void add(int u, int v, int w) {
  e[++ecnt].v = v, e[ecnt].nxt = heads[u], heads[u] = ecnt, e[ecnt].w = w;
}

inline int cmp(int x, int y) { return dep[x] < dep[y] ? x : y; }

inline int getLCA(int x, int y) {
  x = dfn[x], y = dfn[y];
  if (y < x) swap(x, y);
  int k = lg[y - x + 1];
  return cmp(st[x][k], st[y - (1 << k) + 1][k]);
}

inline LL getDis(int x, int y) { return dis[x] + dis[y] - dis[getLCA(x, y)] * 2; }

struct Diameter {
  int x, y;
  LL w;

  inline Diameter operator+(Diameter const &rhs) const {
    if (x == 0) return rhs;
    if (rhs.x == 0) return *this;
    LL d1 = getDis(x, rhs.x), d2 = getDis(x, rhs.y), d3 = getDis(y, rhs.x), d4 = getDis(y, rhs.y);
    Diameter p = *this;
    if (rhs.w > p.w) p = rhs;
    if (d1 > p.w) p = (Diameter){x, rhs.x, d1};
    if (d2 > p.w) p = (Diameter){x, rhs.y, d2};
    if (d3 > p.w) p = (Diameter){y, rhs.x, d3};
    if (d4 > p.w) p = (Diameter){y, rhs.y, d4};
    return p;
  }
} res;

struct Node {
  int ls, rs;
  LL s;
  Diameter dia;
} a[N * ST];

void modify(int &u, int l, int r, int x) {
  if (u == 0) u = ++segcnt;
  a[u].dia = (Diameter){x, x, 0};
  a[u].s = fw[x];
  if (l == r) return;
  int mid = (l + r) >> 1;
  dep[x] <= mid ? modify(a[u].ls, l, mid, x) : modify(a[u].rs, mid + 1, r, x);
}

void merge(int &x, int y, int l, int r) {
  if ((x && y) == false) return x |= y, void();
  int mid = (l + r) >> 1;
  merge(a[x].ls, a[y].ls, l, mid);
  merge(a[x].rs, a[y].rs, mid + 1, r);
  a[x].s += a[y].s;
  a[x].dia = (a[x].dia + a[y].dia);
}

void query(int x, int l, int r, int L, int R) {
  if (L <= l && r <= R) {
    sum += a[x].s;
    res = (res + a[x].dia);
    return;
  }
  int mid = (l + r) >> 1;
  if (L <= mid) query(a[x].ls, l, mid, L, R);
  if (mid < R) query(a[x].rs, mid + 1, r, L, R);
}

void dfs(int u) {
  dfn[u] = ++dcnt;
  euler[dcnt] = u;
  maxdep = max(maxdep, dep[u]);
  for (int i = heads[u], v; i; i = e[i].nxt) {
    dep[v = e[i].v] = dep[u] + 1;
    dis[v] = dis[u] + e[i].w;
    dfs(v);
    euler[++dcnt] = u;
  }
}

void dfs2(int u) {
  modify(rt[u], 1, maxdep, u);
  for (int i = heads[u]; i; i = e[i].nxt) {
    dfs2(e[i].v);
    merge(rt[u], rt[e[i].v], 1, maxdep);
  }
  for (vector<int>::iterator i = q[u].begin(), ilim = q[u].end(); i != ilim; ++i) {
    res = (Diameter){0, 0, 0}, sum = 0;
    query(rt[u], 1, maxdep, dep[u], min(dep[u] + *i, maxdep));
    ans ^= (sum - fw[u]) * 2 - res.w;
  }
}

inline int main() {
  cin >> n >> m;
  for (int i = 2, p, w; i <= n; ++i) {
    cin >> p >> w;
    add(p, i, w);
    fw[i] = w;
  }
  for (int i = 1, r, d; i <= m; ++i) {
    cin >> r >> d;
    q[r].push_back(d);
  }
  dep[1] = 1, dfs(1);
  for (int i = 1; i <= dcnt; ++i) st[i][0] = euler[i];
  lg[1] = 0;
  for (int i = 2; i <= n * 2 + 1; ++i) lg[i] = lg[i / 2] + 1;
  for (int j = 1; j <= lg[dcnt]; ++j) {
    for (int i = 1; i + (1 << j) - 1 <= dcnt; ++i) {
      st[i][j] = cmp(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
    }
  }
  dfs2(1);
  cout << ans;
  return 0;
}

}  // namespace BlueQuantum

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen("tree.in", "r", stdin);
  freopen("tree.out", "w", stdout);
#endif
#endif

  ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
  return BlueQuantum::main();
}
